package cn.com.nes.site.module.dao.design;

import cn.com.nes.common.util.DBUtils;
import cn.com.nes.common.util.ParameterUtil;
import cn.com.nes.site.entity.DataReq;
import cn.com.nes.site.entity.PageData;
import cn.com.nes.site.entity.dto.CalculateTreeDto;
import cn.com.nes.site.module.dao.BaseDaoImpl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.sql.Connection;
import java.text.DecimalFormat;
import java.util.*;

@Repository
public class CalculateDaoImpl extends BaseDaoImpl {

    public PageData getCityTreeOfWeatherParamManage(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("获取城市列表失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        Map<String, Object> data = new HashMap<>();
        try {
            conn = DBUtils.getJNDIDBConn();
            String name = (String) req.getReqData().get("name");

            sb.append("select id, name from hy_province");
            List<Map<String, Object>> list = this.queryForList(conn, sb.toString(), new Object[]{});
            List<CalculateTreeDto> firsts = JSON.parseArray(JSONObject.toJSONString(list), CalculateTreeDto.class);

            sb.delete(0, sb.length());
            sb.append("select b.Id as pid, b.Name as pidName, a.id, a.Name \n" +
                    " from hy_city a\n" +
                    " inner join hy_province b on b.Id = a.PId\n ");
            sb.append(StrUtil.isNotEmpty(name) ? " where (a.name like concat('%','" + name + "','%') or b.name like concat('%','" + name + "','%')  )" : "");
            sb.append(" group by b.Id, a.Id\n" +
                    " order by b.Id, a.Id");
            List<Map<String, Object>> list2 = this.queryForList(conn, sb.toString(), new Object[]{});
            List<CalculateTreeDto> seconds = JSON.parseArray(JSONObject.toJSONString(list2), CalculateTreeDto.class);
            Iterator<CalculateTreeDto> iterator = firsts.iterator();
            while (iterator.hasNext()) {
                CalculateTreeDto first = iterator.next();
                List<CalculateTreeDto> children = new ArrayList<>();
                for (CalculateTreeDto second : seconds) {
                    if (second.getPid().equals(first.getId())) {
                        children.add(second);
                    }
                }
                if (CollUtil.isEmpty(children)) {
                    iterator.remove();
                } else {
                    first.setChildrens(children);
                }
            }
            data.put("dic", firsts);
            res.setData(data);
            res.setRetCode(0);
            res.setRetMessage("ok");
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    public PageData getDetailsOfWeatherParamManage(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("获取气象参数详情失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        Map<String, Object> data = new HashMap<>();
        try {
            conn = DBUtils.getJNDIDBConn();

            String cityId = (String) req.getReqData().get("id");

            sb.append("select b.Name as cityName, c.Name as provinceName,d.Name as countryName, a.CId, a.DistrictCode, format(a.JD, 2) as JD,\n" +
                    "format(a.WD, 2) as WD,format(a.XjDqy, 2) as XjDqy,format(a.XjKtSwGqWd, 2) as XjKtSwGqWd," +
                    "format(a.XjKtSwSqWd, 2) as XjKtSwSqWd,format(a.XjTfSwGqWd, 2) as XjTfSwGqWd,format(a.XjJsRJC, 2) as XjJsRJC," +
                    "format(a.XjKtRPjWd, 2) as XjKtRPjWd,format(a.XjSwPjFs, 2) as XjSwPjFs," +
                    "format(a.XjTfSwXdSd, 2) as XjTfSwXdSd,a.XjKtDqTmDDj," +
                    "format(a.DjDqy, 2) as DjDqy,format(a.ZRYPjXdSd, 2) as ZRYPjXdSd,format(a.DjCnSwGqWd, 2) as DjCnSwGqWd," +
                    "format(a.DjKtSwGqWd, 2) as DjKtSwGqWd,format(a.DjTfSwGqWd, 2) as DjTfSwGqWd," +
                    "format(a.DjKtSwXdSd, 2) as DjKtSwXdSd,format(a.DjSwPjFs, 2) as DjSwPjFs,format(a.DjSwZdFxPjFs, 2) as DjSwZdFxPjFs," +
                    "format(a.DjLfStCxXz_N, 2) as DjLfStCxXz_N,format(a.ZlYPjXdSd, 2) as ZlYPjXdSd,format(a.DjLfStCxXz_E, 2) as DjLfStCxXz_E," +
                    "format(a.DjLfStCxXz_NE, 2) as DjLfStCxXz_NE,format(a.DBMZRYPJWD, 2) as DjLfStCxXz_S,format(a.DBMZRYPJWD, 2) as DjLfStCxXz_SE," +
                    "format(a.DBMZRYPJWD, 2) as DjLfStCxXz_SW," +
                    "format(a.DjLfStCxXz_NW, 2) as DjLfStCxXz_NW,format(a.DjLfStCxXz_W, 2) as DjLfStCxXz_W,format(a.DBMNPJWD, 2) as DBMNPJWD," +
                    "format(a.DBMZLYPJWD, 2) as DBMZLYPJWD,format(a.DBMZRYPJWD, 2) as DBMZRYPJWD" +
                    " from hy_weather2 a\n" +
                    " inner join hy_city b on b.ID = a.CId\n" +
                    " inner join hy_province c on c.Id = b.PId\n" +
                    " inner join hy_country d on d.Id = c.CId " +
                    " where a.CId = ?");
            List<Map<String, Object>> list = this.queryForList(conn, sb.toString(), new Object[]{cityId});
            if (CollUtil.isNotEmpty(list)) {
                data.put("detail", list);
            }

            res.setData(data);
            res.setRetCode(0);
            res.setRetMessage("ok");
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    public PageData getTypeTreeOfBuildingEnvelopeManage(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("获取围护结构列表失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        Map<String, Object> data = new HashMap<>();
        try {
            conn = DBUtils.getJNDIDBConn();
            String name = (String) req.getReqData().get("name");
            sb.append("select id, name from hy_bsdalei");
            List<Map<String, Object>> list = this.queryForList(conn, sb.toString(), new Object[]{});
            List<CalculateTreeDto> firsts = JSON.parseArray(JSONObject.toJSONString(list), CalculateTreeDto.class);

            sb.delete(0, sb.length());
            sb.append("select b.Id as pid, b.Name as pidName, a.id, a.Name \n" +
                    " from hy_bstype a\n" +
                    " inner join hy_bsdalei b on b.Id = a.BSDLId\n");
            sb.append(StrUtil.isNotEmpty(name) ? " where (a.name like concat('%','" + name + "','%') or b.name like concat('%','" + name + "','%')  )" : "");
            sb.append(" group by b.Id, a.Id\n" +
                    " order by b.Id, a.Id");
            List<Map<String, Object>> list2 = this.queryForList(conn, sb.toString(), new Object[]{});
            List<CalculateTreeDto> seconds = JSON.parseArray(JSONObject.toJSONString(list2), CalculateTreeDto.class);
            Iterator<CalculateTreeDto> iterator = firsts.iterator();
            while (iterator.hasNext()) {
                CalculateTreeDto first = iterator.next();
                List<CalculateTreeDto> children = new ArrayList<>();
                for (CalculateTreeDto second : seconds) {
                    if (second.getPid().equals(first.getId())) {
                        children.add(second);
                    }
                }
                if (CollUtil.isEmpty(children)) {
                    iterator.remove();
                } else {
                    first.setChildrens(children);
                }
            }
            data.put("dic", firsts);
            res.setData(data);
            res.setRetCode(0);
            res.setRetMessage("ok");
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    public PageData getDetailsOfOfBuildingEnvelopeManage(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("获取围护结构详情失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        Map<String, Object> data = new HashMap<>();
        try {
            conn = DBUtils.getJNDIDBConn();
            String typeId = (String) req.getReqData().get("id");
            sb.append("select b.BSTId, b.Name, a.*\n" +
                    "from hy_boundingstructure a\n" +
                    "inner join hy_bscode b on b.id = a.BSCId\n" +
                    "inner join hy_bstype c on c.Id = b.BSTId\n" +
                    "where c.Id = ?");
            List<Map<String, Object>> list = this.queryForList(conn, sb.toString(), new Object[]{typeId});

            if (CollUtil.isNotEmpty(list)) {
                List<JSONObject> buildingEnvelopeList = new ArrayList<>();
                List<Object> buildingEnvelopeDetailList = new ArrayList<>();
                for (Map<String, Object> map : list) {
                    JSONObject buildingEnvelope = new JSONObject();
                    buildingEnvelope.put("name", map.get("Name"));
                    buildingEnvelope.put("id", map.get("Id"));
                    buildingEnvelopeList.add(buildingEnvelope);
                    String houDuS = (String) map.get("HouDuS");
                    String xzXsS = (String) map.get("XzXsS");
                    String[] hd = houDuS.split(",");
                    String[] xzxs = xzXsS.split(",");

                    List<Map<String, Object>> detailList = new ArrayList<>();
                    sb.delete(0, sb.length());
                    sb.append("select * from hy_timbering where Id in (" + map.get("TIdS") + ")");
                    List<Map<String, Object>> list1 = this.queryForList(conn, sb.toString(), new Object[]{});
                    for (int i = 0; i < list1.size(); i++) {
                        HashMap<String, Object> detailMap = new HashMap<>();
                        detailMap.put("name", list1.get(i).get("Name"));
                        detailMap.put("hd", hd[i]);
                        detailMap.put("xzxs", xzxs[i]);
                        detailList.add(detailMap);
                    }
                    buildingEnvelopeDetailList.add(detailList);
                }
                data.put("list", buildingEnvelopeList);
                data.put("details", buildingEnvelopeDetailList);
            }
            res.setData(data);
            res.setRetCode(0);
            res.setRetMessage("ok");
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    public PageData getTypeTreeOfMaterialQualityManage(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("获取材质管理列表失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        Map<String, Object> data = new HashMap<>();
        try {
            conn = DBUtils.getJNDIDBConn();
            String name = (String) req.getReqData().get("name");
            sb.append("select id , name from hy_timberingtype");
            List<Map<String, Object>> list = this.queryForList(conn, sb.toString(), new Object[]{});
            List<CalculateTreeDto> firsts = JSON.parseArray(JSONObject.toJSONString(list), CalculateTreeDto.class);

            sb.delete(0, sb.length());
            sb.append("select b.Id as pid, b.Name as pidName, a.id, a.Name \n" +
                    " from hy_timbering a\n" +
                    " inner join hy_timberingtype b on b.Id = a.TTId\n");
            sb.append(StrUtil.isNotEmpty(name) ? " where (a.name like concat('%','" + name + "','%') or b.name like concat('%','" + name + "','%')  )" : "");
            sb.append(" group by b.Id, a.Id\n" +
                    " order by b.Id, a.Id");
            List<Map<String, Object>> list2 = this.queryForList(conn, sb.toString(), new Object[]{});
            List<CalculateTreeDto> seconds = JSON.parseArray(JSONObject.toJSONString(list2), CalculateTreeDto.class);
            Iterator<CalculateTreeDto> iterator = firsts.iterator();
            while (iterator.hasNext()) {
                CalculateTreeDto first = iterator.next();
                List<CalculateTreeDto> children = new ArrayList<>();
                for (CalculateTreeDto second : seconds) {
                    if (second.getPid().equals(first.getId())) {
                        children.add(second);
                    }
                }
                if (CollUtil.isEmpty(children)) {
                    iterator.remove();
                } else {
                    first.setChildrens(children);
                }
            }
            data.put("dic", firsts);
            res.setData(data);
            res.setRetCode(0);
            res.setRetMessage("ok");
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    public PageData getDetailsOfMaterialQualityManage(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("获取材质管理明细失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        Map<String, Object> data = new HashMap<>();
        try {
            conn = DBUtils.getJNDIDBConn();
            String id = (String) req.getReqData().get("id");
            sb.append("select b.Name as type, a.id, a.TTId, a.Name, format(a.BRr, 2) as BRr, format(a.GMD, 2) as GMD, format(a.DrXs, 2) as DrXs\n" +
                    "from hy_timbering a\n" +
                    "inner join hy_timberingtype b on b.Id = a.TTId\n" +
                    "where a.Id = ?");
            List<Map<String, Object>> list = this.queryForList(conn, sb.toString(), new Object[]{id});
            if (CollUtil.isNotEmpty(list)) {
                data.put("detail", list.get(0));
            }
            res.setData(data);
            res.setRetCode(0);
            res.setRetMessage("ok");
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    public PageData saveMaterialQuality(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("获取材质管理明细失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        Map<String, Object> data = new HashMap<>();
        try {
            conn = DBUtils.getJNDIDBConn();
            String id = (String) req.getReqData().get("id");
            String typeId = (String) req.getReqData().get("typeId");
            String name = (String) req.getReqData().get("name");
            String brr = (String) req.getReqData().get("BRr");
            String gmd = (String) req.getReqData().get("GMD");
            String drxs = (String) req.getReqData().get("DrXs");


            if (StrUtil.isEmpty(id)) { // 新增
                sb.append("select count(1) from hy_timbering where name = ?");
                int i = this.queryForInt(conn, sb.toString(), new Object[]{name});
                if (i > 0) {
                    res.setRetMessage("存在相同名称的材质");
                    return res;
                }

                sb.delete(0, sb.length());
                sb.append("insert into hy_timbering(TTId,Name,BRr,GMD,DrXs,Version,CommonFlag) values(?,?,?,?,?,?,0)");
                this.update(conn, sb.toString(), new Object[]{typeId, name, brr, gmd, drxs, System.currentTimeMillis()});
            } else {    //修改
                sb.append("select count(1) from hy_timbering where name = ? and id<>?");
                int i = this.queryForInt(conn, sb.toString(), new Object[]{name, id});
                if (i > 0) {
                    res.setRetMessage("存在相同名称的材质");
                    return res;
                }

                sb.delete(0, sb.length());
                sb.append("update hy_timbering set Version = ?");
                List<Object> objects = new ArrayList<>();
                objects.add(System.currentTimeMillis());
                if (StrUtil.isNotEmpty(name)) {
                    sb.append(",Name=?");
                    objects.add(name);
                }
                if (StrUtil.isNotEmpty(brr)) {
                    sb.append(",BRr=?");
                    objects.add(brr);
                }
                if (StrUtil.isNotEmpty(gmd)) {
                    sb.append(",GMD=?");
                    objects.add(gmd);
                }
                if (StrUtil.isNotEmpty(drxs)) {
                    sb.append(",DrXs=?");
                    objects.add(drxs);
                }
                if (StrUtil.isNotEmpty(typeId)) {
                    sb.append(",TTId=?");
                    objects.add(typeId);
                }
                sb.append(" where id = ?");
                objects.add(id);
                this.update(conn, sb.toString(), objects.toArray());
            }

            res.setData(data);
            res.setRetCode(0);
            res.setRetMessage("ok");
            conn.commit();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    public PageData calculateHeatLoad(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("计算失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        try {
            conn = DBUtils.getJNDIDBConn();

            String buildingEnvelopeId = ParameterUtil.getString(req, "RFHbody4ListID"); // 围护结构ID
            Double floorage = ParameterUtil.getDouble(req, "RFHbuildingArea"); // 建筑面积
            Double summerIndoorDesignTemperature = Double.parseDouble(String.valueOf(req.getReqData().get("RFHXiaJiSNSJWD"))); // 夏季室内设计温度
            Double winterIndoorDesignTemperature = Double.parseDouble(String.valueOf(req.getReqData().get("RFHDongJiSNSJWD"))); // 冬季室内设计温度
            Double summerOutdoorTemperature = Double.parseDouble(String.valueOf(req.getReqData().get("RFHXjKtSwGqWd"))); // 夏季室外温度
            Double winterOutdoorTemperature = Double.parseDouble(String.valueOf(req.getReqData().get("RFHDjKtSwGqWd"))); // 冬季室外温度

            // 根据围护结构ID查询围护详情
            sb.append("select * from hy_boundingstructure where BSCId = " + buildingEnvelopeId);
            List<Map<String, Object>> buildingEnvelopes = queryForList(conn, sb.toString(), new Object[]{});
            String HouDuS = (String) buildingEnvelopes.get(0).get("HouDuS");
            String[] houDuS = HouDuS.split(",");
            String TIdS = (String) buildingEnvelopes.get(0).get("TIdS");
            String[] tids = TIdS.split(",");
            // 创建材质和厚度映射关系
            HashMap<Integer, String> houdus = new HashMap<>();
            for (int i = 0; i < tids.length; i++) {
                houdus.put(Integer.valueOf(tids[i]), houDuS[i]);
            }

            // 根据围护详情的材质，查询对应材质的导热系数
            sb.delete(0, sb.length());
            sb.append("select * from hy_timbering where Id in (" + buildingEnvelopes.get(0).get("TIdS") + ")");
            List<Map<String, Object>> materials = queryForList(conn, sb.toString(), new Object[]{});
            Double summerHeatLoad = heatLoad(floorage, summerIndoorDesignTemperature, summerOutdoorTemperature, houdus, materials);
            Double winterHeatLoad = heatLoad(floorage, winterIndoorDesignTemperature, winterOutdoorTemperature, houdus, materials);

            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("summerHeatLoad", summerHeatLoad);
            resultMap.put("winterHeatLoad", winterHeatLoad);
            res.setData(resultMap);
            res.setRetCode(0);
            res.setRetMessage("ok");
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }

    /**
     * 热负荷计算
     *
     * @param f           建筑面积
     * @param tn          室内温度
     * @param tw          室外温度
     * @param houDuSSplit 厚度
     * @param materials   材质
     * @return
     */
    private Double heatLoad(Double f, Double tn, Double tw, HashMap<Integer, String> houDuSSplit, List<Map<String, Object>> materials) {
        int a = 1; // 温差修正系数，当前指定为1
        DecimalFormat df = new DecimalFormat("#0.000");
        Double k = 0d;
        for (int i = 0; i < materials.size(); i++) {
            BigDecimal drXs = new BigDecimal(String.valueOf(materials.get(i).get("DrXs")));
            drXs = drXs.setScale(3, BigDecimal.ROUND_HALF_UP);
            Double drxs = Double.parseDouble(drXs.toString());
            BigDecimal houDu = new BigDecimal(houDuSSplit.get(materials.get(i).get("Id")));
            houDu = houDu.divide(new BigDecimal(1000));
            houDu= houDu.setScale(3, BigDecimal.ROUND_HALF_UP);
            Double houdu = Double.parseDouble(houDu.toString());
            String name = (String) materials.get(i).get("Name");
            System.out.println(name + " 厚度：" + houdu + " 导热系数：" + drxs);
            Double z = Double.parseDouble(new BigDecimal(String.valueOf(houdu / drxs)).setScale(3, BigDecimal.ROUND_HALF_UP).toString());
            k = k + z;
        }
        k = Double.parseDouble(new BigDecimal(k).setScale(3, BigDecimal.ROUND_HALF_UP).toString());
        k = 1 / (k + 0.11 + 0.04);
        k = Double.valueOf(df.format(k));
        System.out.println("k = " + k);
        double s = k * f * (tn - tw) * a;
        return s;
    }

    public PageData deleteCalculate(DataReq req) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("删除计算数据失败");
        Connection conn = null;
        StringBuffer sb = new StringBuffer();
        try {
            conn = DBUtils.getDBConn_Ope();

            List<Integer> ids = (List<Integer>) req.getReqData().get("ids");
            for (Integer id : ids) {
                sb.append("delete from heating_system_solution where id=?");
                this.update(conn, sb.toString(), new Object[]{id});
            }
            res.setRetCode(0);
            res.setRetMessage("ok");
            conn.commit();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return res;
    }
}
